/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#include <map>
#include <vector>

#include "IKeyListener.h"
#include "IMouseListener.h"

/*-----------------------------------
    Input Property Flags
------------------------------------*/
enum Input_t {
    IF_IRRLICHT = (1<<0)
};



/**
===============================================
Input Property Settings Write Access
===============================================
*/
struct InputProperties
{
    bool joystickAvailible;
    bool registerInput;
};

/**
===============================================
Input Property Settings Read only Access
===============================================
*/
const struct InputSettings
{
    InputSettings( InputProperties p ) : m_properties(p) {};

    /** Is there a Joystick */
    bool HasJoystick()  const { return m_properties.joystickAvailible; };
    /** Should we register input */
    bool RegisterInput() const { return m_properties.registerInput; };
private:
    InputProperties  m_properties;
};

/**
=============================
Input subsystem interface
=============================
*/
class IInput
{
public:
    /** Initialize the input system */
    virtual int Init( const InputSettings &settings )=0;
    /** Poll for events */
	virtual void Update(float dt)=0;
    /** Shutdown */
	virtual void Shutdown()=0;

    /*----------------------------
        Handle Joystick Input
    -----------------------------*/

    /** Test to see if there is a joystick availible, return the count */
    virtual int CheckJoystick()=0;
    /** Enable the joystick module */
    virtual void EnableJoystick()=0;
    /** Test to see if the joystick module is up */
    bool JoystickEnabled() { return m_joystickEnabled; };
    /** Check the x-axis */
    virtual int GetJoystickX()=0;
    /** Check the y-axis */
    virtual int GetJoystickY()=0;
    /** Test to see if a button is down */
    virtual int IsJoystickButtonDown(int button, bool stamp=false)=0;

    /*----------------------------
        Handle the mouse 
    -----------------------------*/

    /** Get the mouse x-pos */
    virtual int GetMouseX()=0;
    /** Get the mouse y-pos */
	virtual int GetMouseY()=0;

    /** Get the change in x */
    virtual int GetDeltaMX()=0;
    /** Get the change in y */
    virtual int GetDeltaMY()=0;
    /** Test to see if a mouse button is down */
    virtual bool IsButtonDown( int button, bool stamp=false )=0;
    /** Test to see if a button is released */
    virtual bool ButtonReleased( int button )=0;

    /*---------------------------------
        Handle keyboard 
    ----------------------------------*/

    /** Test to see if a key is down */
    virtual bool IsKeyDown( int key, bool stamp=false )=0;
    /** Test to see if a key is released */
    virtual bool KeyReleased( int key )=0;
    
    /*----------------------------------
        Handle Input Listeners
    ------------------------------------*/

    /** Add a Keyboard listener */
    void AddKeyListener( IKeyListener* l ) { m_KeyListeners.push_back( l ); };
    
    /** Remove a Keyboard listener */
    void RemoveKeyListener( IKeyListener* l ) { 
        type_KeyListenerList::iterator it = m_KeyListeners.begin();
        for(; it != m_KeyListeners.end(); ++it )
            if ( (*it) == l ) {
                m_KeyListeners.erase( it );
                return;
            }
    };

    /** Add a Mouse listener */
    void AddMouseListener( IMouseListener* l ) { m_MouseListeners.push_back( l ); };
    
    /** Remove a Mouse listener */
    void RemoveMouseListener( IMouseListener* l ) { 
        type_MouseListenerList::iterator it = m_MouseListeners.begin();
        for(; it != m_MouseListeners.end(); ++it )
            if ( (*it) == l ) {
                m_MouseListeners.erase( it );
                return;
            }
    };

protected:
    /**
        KeyEvent Listeners
    */
    typedef std::vector< IKeyListener* >    type_KeyListenerList;
    type_KeyListenerList    m_KeyListeners;

    /**
        MouseEvent Listeners
    */
    typedef std::vector< IMouseListener* >    type_MouseListenerList;
    type_MouseListenerList    m_MouseListeners;


    // if joystick is availible
    bool m_joystickEnabled;
};

